﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace SGUI
{
    public class SGSprite : UIElement
    {
        SGAtlas Atlas;
        UISpriteData spriteData;
        public override void Init()
        {
            this.AddProperty("Src", "", Property_Src_Set);
            this.AddProperty("Type","Simple",this.Property_Type_Set);
            this.AddProperty("SliceBorder","0,0,0,0");
            base.Init();
            this.SetProperty("Width",-1d);
            this.SetProperty("Height", -1d);
        }
        public void Property_Src_Set(object newValue, object oldValue)
        {
            HasChanged = true;
            string SpritePath = (string)newValue;
            string[] strArr = SpritePath.Split('/');
            Atlas = UIManager.Atlas.GetAtlas(strArr[0]);
            this.spriteData = Atlas.GetSprite(strArr[1]);
        }

        public void Property_Type_Set(object newValue,object oldValue) 
        {
            HasChanged = true;
        }

        public override void OnEnter()
        {
            string SpritePath = this.PropertyValue<string>("Src");
            string[] strArr = SpritePath.Split('/');
            Atlas = UIManager.Atlas.GetAtlas(strArr[0]);
            this.spriteData = Atlas.GetSprite(strArr[1]);
            if (this.PropertyValue<double>("Width") == -1d)
            {
                this.SetProperty("Width", (double)spriteData.width, false);

            }
            if (this.PropertyValue<double>("Height") == -1d)
            {
                this.SetProperty("Height", (double)spriteData.height, false);
            }
            this.GenSelfMesh();
            this.GenRender();
            UpdateToRender();
            base.OnEnter();
        }

        public override void GenSelfMesh()
        {
            this.color = SGTools.ColorFromHTML(this.PropertyValue<string>("Color"));
            this.mGeom = new UIGeometry();
            this.mGeom.verts = new List<Vector3>();
            this.mGeom.cols = new List<Color>();
            this.mGeom.uvs = new List<Vector2>();
            this.GenMesh();       
        }


        public void GenMesh() 
        {
            string strType = this.PropertyValue<string>("Type");
            switch (strType) 
            {
                case "Simple":
                   this.SimpleFill();
                break;
                case "Slice":
                   this.SliceFill();
                break;
            }
           
        }

        void SimpleFill() 
        {
            //Vector
            Vector4 size = this.GetElementSize();
            float Scale = (float)this.PropertyValue<double>("Scale");
            this.mGeom.verts.Add(new Vector3(size.x * Scale, size.y * Scale, 0)); //minx,miny
            this.mGeom.verts.Add(new Vector3(size.z * Scale, size.y * Scale, 0)); //maxx,miny
            this.mGeom.verts.Add(new Vector3(size.x * Scale, size.w * Scale, 0)); //minx,maxy
            this.mGeom.verts.Add(new Vector3(size.z * Scale, size.w * Scale, 0)); //maxx,maxy
            //Color
            this.mGeom.cols.Add(this.color);
            this.mGeom.cols.Add(this.color);
            this.mGeom.cols.Add(this.color);
            this.mGeom.cols.Add(this.color);

            float Minx = spriteData.x / Atlas.Mat.mainTexture.width;
            float Maxx = (spriteData.x + spriteData.width) / Atlas.Mat.mainTexture.width;
            float Miny = 1 - (spriteData.y / Atlas.Mat.mainTexture.height);
            float Maxy = 1 - ((spriteData.y + spriteData.height) / Atlas.Mat.mainTexture.height);
            //UV
            this.mGeom.uvs.Add(new Vector2(Minx, Maxy));
            this.mGeom.uvs.Add(new Vector2(Maxx, Maxy));
            this.mGeom.uvs.Add(new Vector2(Minx, Miny));
            this.mGeom.uvs.Add(new Vector2(Maxx, Miny));
        }
        void SliceFill() 
        {
            /*
             _____________
             |__|_____|__|
             |  |     |  |
             |__|_____|__|
             |__|_____|__|
            */
            Vector4 size = this.GetElementSize();
            double[] sliceSizeArr = SGTools.StringToNumberArr(this.PropertyValue<string>("SliceBorder"));
            float top = (float)sliceSizeArr[0], bottom = (float)sliceSizeArr[1], left = (float)sliceSizeArr[2], right = (float)sliceSizeArr[3];
            
            float Width = (float)this.PropertyValue<double>("Width");
            float Height = (float)this.PropertyValue<double>("Height");
            
            float sptop = top / spriteData.height * Height;
            float spbottom = bottom / spriteData.width * Height;
            float spleft = left / spriteData.width * Width;
            float spright = right / spriteData.width * Width;
            
            float Scale = (float)this.PropertyValue<double>("Scale");

            float Minx = spriteData.x / Atlas.Mat.mainTexture.width;
            float Maxx = (spriteData.x + spriteData.width) / Atlas.Mat.mainTexture.width;
            float Miny = 1 - (spriteData.y / Atlas.Mat.mainTexture.height);
            float Maxy = 1 - ((spriteData.y + spriteData.height) / Atlas.Mat.mainTexture.height);

           float uvtop =top /  (float)Atlas.Mat.mainTexture.height;
           float uvbottom = bottom / (float)Atlas.Mat.mainTexture.height;
           float uvleft = left / (float)Atlas.Mat.mainTexture.width;
           float uvright = right / (float)Atlas.Mat.mainTexture.width;
           uvtop = uvtop * -1;
           uvbottom = uvbottom * -1;
           
            //Left Top 
            fillQuadByPoint(size.x , size.w   - top, size.x  + left, size.w, Scale);
            fillUVByPoint(Minx, Maxy - uvtop, Minx + uvleft, Maxy);
            

            //Top
            fillQuadByPoint(size.x+ left, size.w - top, size.z  - right, size.w , Scale);
            fillUVByPoint(Minx + uvleft, Maxy - uvtop, Maxx - uvright, Maxy);
            
            //Right Top
            fillQuadByPoint(size.z- right, size.w - top, size.z , size.w , Scale);
            fillUVByPoint(Maxx - uvright, Maxy - uvtop, Maxx, Maxy);
            
            //Left
            fillQuadByPoint(size.x, size.y + bottom, size.x  + left, size.w - top, Scale);
            fillUVByPoint(Minx, Miny + uvbottom, Minx + uvleft, Maxy - uvtop);
            
            //Center
            fillQuadByPoint(size.x + left, size.y + bottom, size.z - right, size.w - top, Scale);
            fillUVByPoint(Minx + uvleft,Miny + uvbottom,Maxx - uvright,Maxy - uvtop);
            
            //Right
            fillQuadByPoint(size.z  - right, size.y + bottom, size.z, size.w  - top, Scale);
            fillUVByPoint(Maxx - uvright, Miny + uvbottom, Maxx, Maxy - uvtop);
            
            //Left Bottom
            fillQuadByPoint(size.x , size.y, size.x  + left, size.y + bottom, Scale);
            fillUVByPoint(Minx, Miny, Minx + uvleft, Miny + uvbottom);
            
            //Bottom
            fillQuadByPoint(size.x + left, size.y , size.z  - right, size.y + bottom, Scale);
            fillUVByPoint(Minx + uvleft, Miny, Maxx - uvright, Miny + uvbottom);
            
            //Left Right
            fillQuadByPoint(size.z - right, size.y , size.z , size.y  + bottom, Scale);
            fillUVByPoint(Maxx - uvright, Miny, Maxx, Miny + uvbottom);
           
            for (int i = 0; i < 4 * 9; i++)
            {
                this.mGeom.cols.Add(this.color);
            }

        }

        void fillUVByPoint(float minX,float minY,float maxX,float maxY) 
        {
            this.mGeom.uvs.Add(new Vector2(minX, minY));
            this.mGeom.uvs.Add(new Vector2(maxX, minY));
            this.mGeom.uvs.Add(new Vector2(minX, maxY));
            this.mGeom.uvs.Add(new Vector2(maxX, maxY));
        }

        void fillQuadByPoint(float minX,float minY,float maxX,float maxY,float scale) 
        {
            this.mGeom.verts.Add(new Vector3(minX * scale, minY * scale, 0)); //minx,miny
            this.mGeom.verts.Add(new Vector3(maxX * scale, minY * scale, 0)); //maxx,miny
            this.mGeom.verts.Add(new Vector3(minX * scale, maxY * scale, 0)); //minx,maxy
            this.mGeom.verts.Add(new Vector3(maxX * scale, maxY * scale, 0)); //maxx,maxy
        }
      

        void GenRender()
        {
            MeshRenderer render = this.gameObject.AddComponent<MeshRenderer>();
            MeshFilter mf = this.gameObject.AddComponent<MeshFilter>();
        }

        public override void UpdateToRender()
        {
            Mesh mesh = new Mesh();
            mesh.vertices = this.mGeom.verts.ToArray();
            mesh.colors = this.mGeom.cols.ToArray();

            int triNumber = this.mGeom.verts.Count / 4 * 2;
            int[] indices = new int[triNumber * 3];

            for (int i = 0; i < triNumber / 2; i++)
            {
                int addstep = i * 4;
                indices[i * 6 + 0] = 0 + addstep;
                indices[i * 6 + 1] = 1 + addstep;
                indices[i * 6 + 2] = 2 + addstep;

                indices[i * 6 + 3] = 1 + addstep;
                indices[i * 6 + 4] = 3 + addstep;
                indices[i * 6 + 5] = 2 + addstep;
            }
            // 9 quad 18 tri 54 index 
            mesh.SetIndices(indices, MeshTopology.Triangles, 0);
            
            mesh.uv = this.mGeom.uvs.ToArray();
            MeshRenderer render = this.gameObject.GetComponent<MeshRenderer>();
            MeshFilter mf = this.gameObject.GetComponent<MeshFilter>();
            mf.sharedMesh = mesh;
            render.material = Atlas.Mat;
            render.material.color = this.color;
        }

    }
}
